/**
 * Copyright (c) 2012-2016, www.tinygroup.org (luo_guo@icloud.com).
 * <p>
 * Licensed under the GPL, Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/gpl.html
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.tinygroup.databasebuinstaller.impl;

import org.tinygroup.database.config.table.Table;
import org.tinygroup.database.table.TableProcessor;
import org.tinygroup.logger.LogLevel;

import java.io.*;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 *
 * 功能说明:数据库表新建、字段更新、删除操作
 *
 * 开发人员: renhui <br>
 * 开发时间: 2013-8-15 <br>
 * <br>
 */
public class TableInstallProcessor extends AbstractInstallProcessor {

    private List<Table> tableList = new ArrayList<Table>();
    private TableProcessor tableProcessor;

    public TableProcessor getTableProcessor() {
        return tableProcessor;
    }

    public void setTableProcessor(TableProcessor tableProcessor) {
        this.tableProcessor = tableProcessor;
    }

    private void deal(String language, Table table, List<String> sqls,
                      Connection connect, boolean isFull) throws SQLException {
        if (tableList.contains(table)) {
            return;
        }
        tableList.add(table);
        installTable(language, table, sqls, connect, isFull);
    }

    private void installTable(String language, Table table, List<String> sqls,
                              Connection connect, boolean isFull) throws SQLException {
        logger.logMessage(LogLevel.INFO, "开始生成表格语句,表格 包:{0},名:{1}",
                table.getPackageName(), table.getName());
        List<String> tableSqls;
        // 非全量且表格已经存在,需要生成增量sql
        if (!isFull && tableProcessor.checkTableExist(table, language, connect)) {
            tableSqls = tableProcessor.getUpdateSql(table,
                    table.getPackageName(), language, connect);
        } else {
            tableSqls = tableProcessor.getCreateSql(table,
                    table.getPackageName(), language);
        }
        if (tableSqls.size() != 0) {
            logger.logMessage(LogLevel.INFO, "生成sql:{0}", tableSqls);
        } else {
            logger.logMessage(LogLevel.INFO, "无需生成Sql");
        }
        sqls.addAll(tableSqls);
        logger.logMessage(LogLevel.INFO, "生成表格语句完成,表格 包:{0},名:{1}",
                table.getPackageName(), table.getName());
    }

    private List<String> getNoStorageSqls(String language, Connection conn,
                                          boolean isFull) throws SQLException {
        logger.logMessage(LogLevel.INFO, "开始获取数据库表安装操作执行语句");
        List<Table> tables = tableProcessor.getTables();
        List<String> sqls = new ArrayList<String>();
        for (Table table : tables) {
            deal(language, table, sqls, conn, isFull);
        }
        logger.logMessage(LogLevel.INFO, "获取数据库表安装操作执行语句结束");
        return sqls;
    }

    private List<String> getSqls(String language, Connection con)
            throws SQLException {
        logger.logMessage(LogLevel.INFO, "开始获取数据库表安装操作执行语句");
        List<Table> filterTables = getModifiedTables();
        List<String> sqls = new ArrayList<String>();
        for (Table table : filterTables) {
            deal(language, table, sqls, con, false);
        }
        logger.logMessage(LogLevel.INFO, "获取数据库表安装操作执行语句结束");
        return sqls;

    }

    private List<Table> getModifiedTables() {
        List<Table> list = tableProcessor.getTables();
        Properties properties = new Properties();
        for (Table table : list) {
            properties.put(table.getId(), String.valueOf(tableProcessor
                    .getLastModifiedTime(table.getId())));
        }
        String temp = System.getProperty("user.home");
        String projectName = new File(System.getProperty("user.dir")).getName();
        File catalog = new File(temp + File.separator + projectName);
        if (!catalog.exists()) {
            catalog.mkdir();
        }
        File proFile = new File(catalog, "tablestime.properties");
        Properties fileProperties = new Properties();
        if (!proFile.exists()) {
            try {
                proFile.createNewFile();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(proFile);
            fileProperties.load(inputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                }
            }
        }
        List<Table> filterTables = new ArrayList<Table>();
        if (fileProperties.size() == 0) {
            filterTables.addAll(list);
            fileProperties.putAll(properties);
        } else {
            Properties newProperties = new Properties();
            for (Object key : properties.keySet()) {
                String proKey = (String) key;
                if (!fileProperties.containsKey(key)
                        || !properties.get(proKey).equals(
                        fileProperties.get(proKey))) {
                    newProperties.put(proKey, properties.get(proKey));
                    filterTables.add(tableProcessor.getTableById(proKey));
                }
            }
            fileProperties.putAll(newProperties);
        }
        OutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(proFile);
            fileProperties.store(outputStream, "表格修改时间信息");
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
            }
        }
        return filterTables;
    }

    public int getOrder() {
        return HIGHEST_PRECEDENCE;
    }

    public List<String> getDealSqls(String language, Connection con)
            throws SQLException {
        return getUpdateSqls(language, con);
    }

    public List<String> getToolDealSqls(String language, Connection con)
            throws SQLException {
        return getNoStorageSqls(language, con, false);
    }

    public List<String> getToolFullSqls(String language) throws SQLException {
        return getNoStorageSqls(language, null, true);
    }

    public List<String> getFullSqls(String language, Connection con)
            throws SQLException {
        return null;
    }

    public List<String> getUpdateSqls(String language, Connection con)
            throws SQLException {
        return getSqls(language, con);
    }

}
